/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */
#ifndef __SINBAD_CHARACTER_H__
#define __SINBAD_CHARACTER_H__

#include "Ogre.h"
#include <OIS/OIS.h>

//From Ogre demo
#define NUM_ANIMS 13           // number of animations the character has
#define CHAR_HEIGHT 5          // height of character's center of mass above ground
#define CAM_HEIGHT 2           // height of camera above character's center of mass
#define RUN_SPEED 17           // character running speed in units per second
#define TURN_SPEED 500.0f      // character turning in degrees per second
#define ANIM_FADE_SPEED 7.5f   // animation crossfade speed in % of full weight per second
#define JUMP_ACCEL 30.0f       // character jump acceleration in upward units per squared second
#define GRAVITY 90.0f          // gravity in downward units per squared second
#define OFF_GROUND 0.01f //character's feet off the ground

namespace OgreCamNav
{
	//From Ogre demo
	class SinbadCharacter
	{
		// all the animations our character has, and a null ID
		// some of these affect separate body parts and will be blended together
		enum AnimID
		{
			ANIM_IDLE_BASE,
			ANIM_IDLE_TOP,
			ANIM_RUN_BASE,
			ANIM_RUN_TOP,
			ANIM_HANDS_CLOSED,
			ANIM_HANDS_RELAXED,
			ANIM_DRAW_SWORDS,
			ANIM_SLICE_VERTICAL,
			ANIM_SLICE_HORIZONTAL,
			ANIM_DANCE,
			ANIM_JUMP_START,
			ANIM_JUMP_LOOP,
			ANIM_JUMP_END,
			ANIM_NONE
		};

		Ogre::Camera* camera;
		Ogre::SceneNode* bodyNode;
		Ogre::SceneNode* cameraPivot;
		Ogre::SceneNode* cameraGoal;
		Ogre::SceneNode* cameraNode;
		Ogre::Real pivotPitch;
		Ogre::Entity* bodyEntity;
		Ogre::Entity* sword1;
		Ogre::Entity* sword2;
		Ogre::RibbonTrail* swordTrail;
		Ogre::RaySceneQuery *rayQuery;

		Ogre::AnimationState* anims[NUM_ANIMS];    // master animation list
		AnimID baseAnimID;                   // current base (full- or lower-body) animation
		AnimID topAnimID;                    // current top (upper-body) animation
		bool fadingIn[NUM_ANIMS];            // which animations are fading in
		bool fadingOut[NUM_ANIMS];           // which animations are fading out
		bool swordsDrawn;
		Ogre::Vector3 keyDirection;      // player's local intended direction based on WASD keys
		Ogre::Vector3 goalDirection;     // actual intended direction in world-space
		Ogre::Real verticalVelocity;     // for jumping
		Ogre::Real timer;                // general timer to see how long animations have been playing
		
		void setupBody(Ogre::SceneManager *sceneMgr);
		void setupCamera(Ogre::Camera *camera);
		void setupAnimations();
		void setBaseAnimation(AnimID id, bool reset = false);
		void setTopAnimation(AnimID id, bool reset = false);	
		void updateCamera(Ogre::Real deltaTime);
		void updateBody(Ogre::Real deltaTime);
		void updateAnimations(Ogre::Real deltaTime);
		void fadeAnimations(Ogre::Real deltaTime);
		void updateCameraGoal(Ogre::Real deltaYaw, Ogre::Real deltaPitch, Ogre::Real deltaZoom);	
		void keepOnGround();
		void setupParticle(Ogre::SceneManager *sceneMgr);
	public:
		SinbadCharacter(Ogre::Camera *camera);
		~SinbadCharacter(void);
		void setPostion(Ogre::Real x,Ogre::Real y,Ogre::Real z);
		void update(Ogre::Real deltaTime);
		void injectMouseMove(const OIS::MouseEvent& evt);
		void injectKeyDown(const OIS::KeyEvent& evt);
		void injectKeyUp(const OIS::KeyEvent& evt);
		void injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id);
	};
}
#endif
